﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Xunit;

namespace homework05_2
{
    public class OrderServiceTests
    {
        private readonly OrderService _orderService;
        private readonly Goods _phone;
        private readonly Goods _computer;
        private readonly Customer _customer1;
        private readonly Customer _customer2;

        public OrderServiceTests()
        {
            _orderService = new OrderService();
            _phone = new Goods("手机", 2000);
            _computer = new Goods("电脑", 5000);
            _customer1 = new Customer("张三");
            _customer2 = new Customer("李四");

            // 初始化测试数据
            var order1 = new Order("001", _customer1);
            order1.AddDetail(new OrderDetails(_phone, 2));
            order1.AddDetail(new OrderDetails(_computer, 1));

            var order2 = new Order("002", _customer2);
            order2.AddDetail(new OrderDetails(_computer, 2));

            _orderService.AddOrder(order1);
            _orderService.AddOrder(order2);
        }

        [Fact]
        public void AddOrder_ShouldAddOrderSuccessfully()
        {
            // Arrange
            var newOrder = new Order("003", _customer1);
            newOrder.AddDetail(new OrderDetails(_phone, 1));

            // Act
            _orderService.AddOrder(newOrder);

            // Assert
            var result = _orderService.QueryByOrderId("003");
            Assert.Single(result);
            Assert.Equal("003", result[0].OrderId);
        }

        [Fact]
        public void AddOrder_ShouldThrowException_WhenOrderIdExists()
        {
            // Arrange
            var duplicateOrder = new Order("001", _customer1);

            // Act & Assert
            var ex = Assert.Throws<Exception>(() => _orderService.AddOrder(duplicateOrder));
            Assert.Equal("订单 001 已存在", ex.Message);
        }

        [Fact]
        public void RemoveOrder_ShouldRemoveOrderSuccessfully()
        {
            // Act
            _orderService.RemoveOrder("001");

            // Assert
            var result = _orderService.QueryByOrderId("001");
            Assert.Empty(result);
        }

        [Fact]
        public void RemoveOrder_ShouldThrowException_WhenOrderNotExists()
        {
            // Act & Assert
            var ex = Assert.Throws<Exception>(() => _orderService.RemoveOrder("999"));
            Assert.Equal("订单 999 不存在", ex.Message);
        }

        [Fact]
        public void UpdateOrder_ShouldUpdateOrderSuccessfully()
        {
            // Arrange
            var updatedOrder = new Order("001", _customer2);
            updatedOrder.AddDetail(new OrderDetails(_computer, 3));

            // Act
            _orderService.UpdateOrder(updatedOrder);

            // Assert
            var result = _orderService.QueryByOrderId("001");
            Assert.Single(result);
            Assert.Equal(_customer2.Name, result[0].Customer.Name);
            Assert.Equal(3, result[0].Details[0].Quantity);
        }

        [Fact]
        public void UpdateOrder_ShouldThrowException_WhenOrderNotExists()
        {
            // Arrange
            var nonExistingOrder = new Order("999", _customer1);

            // Act & Assert
            var ex = Assert.Throws<Exception>(() => _orderService.UpdateOrder(nonExistingOrder));
            Assert.Equal("订单 999 不存在", ex.Message);
        }

        [Fact]
        public void QueryByOrderId_ShouldReturnCorrectOrders()
        {
            // Act
            var result = _orderService.QueryByOrderId("001");

            // Assert
            Assert.Single(result);
            Assert.Equal("001", result[0].OrderId);
        }

        [Fact]
        public void QueryByOrderId_ShouldReturnEmpty_WhenNoMatch()
        {
            // Act
            var result = _orderService.QueryByOrderId("999");

            // Assert
            Assert.Empty(result);
        }

        [Fact]
        public void QueryByGoodsName_ShouldReturnCorrectOrders()
        {
            // Act
            var result = _orderService.QueryByGoodsName("电脑");

            // Assert
            Assert.Equal(2, result.Count);
            Assert.True(result.All(o => o.Details.Any(d => d.Goods.Name.Contains("电脑"))));
        }

        [Fact]
        public void QueryByCustomer_ShouldReturnCorrectOrders()
        {
            // Act
            var result = _orderService.QueryByCustomer("张三");

            // Assert
            Assert.Single(result);
            Assert.Equal("张三", result[0].Customer.Name);
        }

        [Fact]
        public void QueryByAmount_ShouldReturnCorrectOrders()
        {
            // Act
            var result = _orderService.QueryByAmount(5000);

            // Assert
            Assert.Equal(2, result.Count);
            Assert.True(result.All(o => o.TotalAmount >= 5000));
        }

        [Fact]
        public void Sort_ShouldSortOrdersByIdByDefault()
        {
            // Act
            _orderService.Sort();

            // Assert
            var orders = _orderService.QueryByOrderId("");
            Assert.Equal("001", orders[0].OrderId);
            Assert.Equal("002", orders[1].OrderId);
        }

        [Fact]
        public void Sort_ShouldSortOrdersByCustomComparison()
        {
            // Act
            _orderService.Sort((o1, o2) => o2.TotalAmount.CompareTo(o1.TotalAmount));

            // Assert
            var orders = _orderService.QueryByOrderId("");
            Assert.Equal("002", orders[0].OrderId); // 总金额更高
            Assert.Equal("001", orders[1].OrderId);
        }

        [Fact]
        public void ExportAndImport_ShouldWorkCorrectly()
        {
            // Arrange
            var tempFile = Path.GetTempFileName();

            try
            {
                // Act - Export
                _orderService.Export(tempFile);

                // Create new service and import
                var newService = new OrderService();
                newService.Import(tempFile);

                // Assert
                var originalOrders = _orderService.QueryByOrderId("");
                var importedOrders = newService.QueryByOrderId("");

                Assert.Equal(originalOrders.Count, importedOrders.Count);
                for (int i = 0; i < originalOrders.Count; i++)
                {
                    Assert.Equal(originalOrders[i].OrderId, importedOrders[i].OrderId);
                    Assert.Equal(originalOrders[i].TotalAmount, importedOrders[i].TotalAmount);
                }
            }
            finally
            {
                // Cleanup
                if (File.Exists(tempFile))
                {
                    File.Delete(tempFile);
                }
            }
        }

        [Fact]
        public void Import_ShouldThrowException_WhenFileNotExists()
        {
            // Act & Assert
            var ex = Assert.Throws<FileNotFoundException>(() => _orderService.Import("nonexistent.xml"));
            Assert.Contains("nonexistent.xml", ex.Message);
        }
    }
}